package com.dkm.dataScope;

import com.dkm.constant.Constant;
import com.dkm.modules.sys.operator.mapper.UserDataScopeMapper;
import com.dkm.modules.sys.operator.model.UserDatascopePO;
import com.dkm.modules.sys.role.service.RoleService;
import com.dkm.modules.sys.user.model.User;
import com.dkm.modules.sys.user.service.UserService;
import com.dkm.util.HttpContext;
import com.dkm.util.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 数据过滤处理
 *
 * @author ruoyi
 */
@Aspect
@Component
public class DataScopeAspect {
    /**
     * 全部数据权限
     */
    public static final Integer DATA_SCOPE_ALL = 1;

    /**
     * 代理商本人
     */
    public static final Integer DATA_SCOPE_SELF = 2;

    /**
     * 自定数据权限
     */
    public static final Integer DATA_SCOPE_CUSTOM = 3;


    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserDataScopeMapper userDataScopeMapper;


    // 配置织入点
    @Pointcut("@annotation(com.dkm.dataScope.DataScope)")
    public void dataScopePointCut() {
    }

    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point) throws Throwable {
        handleDataScope(point);
    }

    protected void handleDataScope(final JoinPoint joinPoint) {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null || StringUtils.isBlank(controllerDataScope.alias())) {
            return;
        }

        // 获取当前的用户
        User user = (User) ((HttpServletRequest) Objects.requireNonNull(HttpContext.getRequest())).getSession().getAttribute(Constant.USERINFO_SESSION_KEY);
        if (user != null) {
            // 如果是超级管理员，则不过滤数据
            boolean superAmoun = "Y".equals(user.getAdmin());
            // 运营者拥有所有数据权限
            boolean all = Constant.USER_IS_NOT_OPERATOR.equals(user.getIsOperator()) && DATA_SCOPE_ALL.equals(user.getDataPermissions());
            if (superAmoun || all) {
                return;
            }

            dataScopeFilter(joinPoint, user, controllerDataScope);
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param user      用户
     * @param dataScope 权限sql
     */
    public void dataScopeFilter(JoinPoint joinPoint, User user, DataScope dataScope) {
        StringBuilder sqlString = new StringBuilder();

        int dataPermission = user.getDataPermissions() == null ? DATA_SCOPE_SELF : user.getDataPermissions();
        // 代理商登录只可以看到自己的数据
        boolean isOperator = Constant.USER_IS_OPERATOR.equals(user.getIsOperator());
        if (isOperator) {
            dataPermission = DATA_SCOPE_SELF;
        }

        Integer userId = user.getId();
        String alias = dataScope.alias();
        sqlString.append(alias);
        sqlString.append(" ");

        // 自定义权限
        if (DATA_SCOPE_SELF.equals(dataPermission)) {
            sqlString.append("=");
            sqlString.append(" ");
            sqlString.append(userId);
        }

        // 自定义权限
        if (DATA_SCOPE_CUSTOM.equals(dataPermission)) {
            Map<String, Object> param = new HashMap<>();
            param.put(" user_id", userId);
            sqlString.append("in");
            sqlString.append(" ");
            List<UserDatascopePO> operatorPOS = userDataScopeMapper.selectByMap(param);

            if (CollectionUtils.isEmpty(operatorPOS)) {
                sqlString.append(" (-99999) ");
            }else {
                String ids = operatorPOS.stream().map(op -> op.getOperatorId().toString()).collect(Collectors.joining(","));
                sqlString.append(" (");
                sqlString.append(ids);
                sqlString.append(") ");
            }
        }

        Map<String, Object> params = (Map<String, Object>) joinPoint.getArgs()[0];
        params.put(DATA_SCOPE, " AND " + sqlString);
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }
}
